<?php

namespace app\common\library\xmwechat\payment;

use app\common\library\xmwechat\SingletonTrait;
use app\common\library\xmwechat\WechatService;
use EasyWeChat\Pay\Application;
use Symfony\Component\HttpClient\Exception\ClientException;
use Symfony\Component\HttpClient\Exception\ServerException;
use think\facade\Log;

/**
 * 微信合作伙伴（服务商）
 * https://pay.weixin.qq.com/docs/partner/apis/partner-mini-program-payment/partner-mini-prepay.html
 */
class PartnerPayService extends WechatService
{
    protected ?Application $app = null;

    use SingletonTrait;

    public function __construct()
    {
        parent::__construct();
        if (empty($this->wechatPartnerPayConfig['sp_mchid']) || empty($this->wechatPartnerPayConfig['sp_appid']) || empty($this->wechatPartnerPayConfig['sub_mchid']) || empty($this->wechatPartnerPayConfig['secret_key'])) {
            $this->result('请配置服务商支付相关参数');
        }
        $partnerPayConfig = [
            'mch_id'      => $this->wechatPartnerPayConfig['sp_mchid'],
            'secret_key'  => $this->wechatPartnerPayConfig['secret_key'],
            'certificate' => root_path() . $this->wechatPartnerPayConfig['cert_path'],
            'private_key' => root_path() . $this->wechatPartnerPayConfig['key_path'],
            'notify_url'  => $this->wechatPartnerPayConfig['notify_url'],
            'http'        => [
                'throw'   => true, // 状态码非 200、300 时是否抛出异常，默认为开启
                'timeout' => 5.0,
            ],
        ];
        $this->app        = new Application($partnerPayConfig);
    }


    /**
     * 服务商模式支付（小程序）
     * @param array $params
     * @return false|mixed[]|void
     * @author jsjxsz <QQ:1365962177>
     */
    public function pay(array $params)
    {
        if ($params) {
            try {
                $order_no = $params['order_no'];
                $response = $this->app->getClient()->postJson("/v3/pay/partner/transactions/jsapi", [
                    'sp_appid'     => $this->wechatPartnerPayConfig['sp_appid'],// 服务商appid
                    'sp_mchid'     => $this->wechatPartnerPayConfig['sp_mchid'],// 服务商商户号
                    'sub_mchid'    => $this->wechatPartnerPayConfig['sub_mchid'],// 子商户号
                    "out_trade_no" => $params['transaction_no'],// 交易号
                    "description"  => $params['body'],
                    "notify_url"   => $this->wechatPartnerPayConfig['notify_url'],// 回调地址
                    "amount"       => [
                        "total"    => intval($params['pay_price'] * 100),
                        "currency" => "CNY"
                    ],
                    "payer"        => [
                        "sub_openid" => $params['openid']
                    ]
                ]);
                $result   = $response->toArray();
                if (!empty($result['prepay_id'])) {
                    $prepayId = $result['prepay_id'];
                    $utils    = $this->app->getUtils();
                    // 微信小程序appid; 公众号支付需用公众号appid
                    $appId = $params['pay_type'] == 'miniProgram' ? $this->miniProgramConfig['app_id'] : $this->offiAccountConfig['app_id'];
                    // 默认RSA，v2要传MD5
                    $signType  = 'RSA';
                    $payResult = $utils->buildBridgeConfig($prepayId, $appId, $signType);
                    if (isset($payResult['paySign']) && !empty($payResult['paySign'])) {
                        return $payResult;
                    }
                }
            } catch (ServerException|ClientException|\Exception $exception) {
                Log::info('wechatPartnerPay:' . $exception->getMessage());
            }
            return false;
        }
    }

    /**
     * 服务商模式退款（公众号、小程序）
     * @param $params
     * @return bool|string
     * @author jsjxsz <QQ:1365962177>
     */
    public function refunds($params): bool|string
    {
        try {
            $app      = $this->app;
            $response = $app->getClient()->postJson("/v3/refund/domestic/refunds", [
                'sub_mchid'     => $this->wechatPartnerPayConfig['sub_mchid'],// 子商户号
                "out_trade_no"  => $params['out_trade_no'],// 原支付交易对应的商户订单号
                "out_refund_no" => $params['out_refund_no'],// 商户退款单号，商户系统内部的退款单号，退款时生成，唯一
                "reason"        => $params['reason'], //退款原因
                "notify_url"    => $this->wechatPartnerPayConfig['refunds_notify_url'],
                "amount"        => [
                    // 退款金额，单位为分，只能为整数，不能超过原订单支付金额。
                    "refund"   => intval($params['refund_price'] * 100),
                    // 原支付交易的订单总金额，单位为分，只能为整数。
                    "total"    => intval($params['pay_price'] * 100),
                    "currency" => "CNY"
                ]
            ]);
            $result   = $response->toArray();
            if (isset($result['status'])) {
                return $result['status'];
            }
        } catch (ServerException|ClientException|\Exception $exception) {
            Log::info('wechayPartnerRefunds:' . $exception->getMessage());
        }
        return false;
    }

}